home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / hypercrd / xcmd / dxcmds34.sit / Dartmouth XCMD's 3.4.3 / card_14426.txt < prev    next >
Text File  |  1990-04-17  |  13KB  |  436 lines

  1. -- card: 14426 from stack: in.3
  2. -- bmap block id: 14760
  3. -- flags: 4000
  4. -- background id: 13666
  5. -- name: SortField
  6. ----- HyperTalk script -----
  7. on opencard
  8.   hide card field "Source"
  9.   put empty into card field "sorted"
  10.   pass opencard
  11. end opencard
  12.  
  13. on Install
  14.   put ChooseTargetStack() into it
  15.   InstallResource XFCN,SortField,it
  16. end Install
  17.  
  18. on closeCard
  19.   hide msg
  20. end closeCard
  21.  
  22.  
  23. -- part 2 (field)
  24. -- low flags: 01
  25. -- high flags: 0007
  26. -- rect: left=290 top=64 right=292 bottom=397
  27. -- title width / last selected line: 0
  28. -- icon id / first selected line: 0 / 0
  29. -- text alignment: 0
  30. -- font id: 3
  31. -- text size: 9
  32. -- style flags: 0
  33. -- line height: 12
  34. -- part name: unsorted
  35.  
  36.  
  37. -- part 3 (button)
  38. -- low flags: 00
  39. -- high flags: 8003
  40. -- rect: left=76 top=298 right=320 bottom=176
  41. -- title width / last selected line: 0
  42. -- icon id / first selected line: 0 / 0
  43. -- text alignment: 1
  44. -- font id: 0
  45. -- text size: 12
  46. -- style flags: 0
  47. -- line height: 16
  48. -- part name: SortField
  49. ----- HyperTalk script -----
  50. on mouseUp
  51.   put empty into card field "sorted"
  52.   put the ticks into t1
  53.   put SortField(card field "unsorted") into card field "sorted"
  54.   put the ticks into t2
  55.   put "time: "&t2-t1&&"ticks"
  56.   get the number of lines in card field unsorted
  57.   put " for "&it&" lines" after msg
  58. end mouseUp
  59.  
  60.  
  61.  
  62. -- part 6 (button)
  63. -- low flags: 00
  64. -- high flags: 8003
  65. -- rect: left=299 top=298 right=320 bottom=438
  66. -- title width / last selected line: 0
  67. -- icon id / first selected line: 0 / 0
  68. -- text alignment: 1
  69. -- font id: 0
  70. -- text size: 12
  71. -- style flags: 0
  72. -- line height: 16
  73. -- part name: Hide C Source
  74. ----- HyperTalk script -----
  75. on mouseUp
  76.   get the visible of card field "Source"
  77.   set the visible of card field "Source" to not it
  78.   if it is false then
  79.     set the name of me to "Hide C Source"
  80.   else
  81.     set the name of me to "Show C Source"
  82.   end if
  83. end mouseUp
  84.  
  85.  
  86.  
  87. -- part 8 (field)
  88. -- low flags: 01
  89. -- high flags: 0007
  90. -- rect: left=395 top=64 right=292 bottom=491
  91. -- title width / last selected line: 0
  92. -- icon id / first selected line: 0 / 0
  93. -- text alignment: 0
  94. -- font id: 3
  95. -- text size: 9
  96. -- style flags: 0
  97. -- line height: 12
  98. -- part name: sorted
  99.  
  100.  
  101. -- part 9 (field)
  102. -- low flags: 01
  103. -- high flags: 2007
  104. -- rect: left=18 top=33 right=292 bottom=290
  105. -- title width / last selected line: 0
  106. -- icon id / first selected line: 0 / 0
  107. -- text alignment: 0
  108. -- font id: 3
  109. -- text size: 10
  110. -- style flags: 0
  111. -- line height: 13
  112. -- part name: Documentation
  113.  
  114.  
  115. -- part 7 (field)
  116. -- low flags: 81
  117. -- high flags: 0007
  118. -- rect: left=18 top=31 right=291 bottom=490
  119. -- title width / last selected line: 0
  120. -- icon id / first selected line: 0 / 0
  121. -- text alignment: 0
  122. -- font id: 3
  123. -- text size: 10
  124. -- style flags: 0
  125. -- line height: 13
  126. -- part name: Source
  127.  
  128.  
  129. -- part contents for card part 2
  130. ----- text -----
  131. knockwurst
  132. charlie
  133. monkey
  134. ernest
  135. wascally wabbit
  136. gamma
  137. rapscallion
  138. horse
  139. ice cream
  140. able
  141. jumping jack flash
  142. liver
  143. underwhelmed
  144. no way, jose
  145. baker
  146. occularity
  147. zenzational
  148. penelope
  149. dog
  150. qwerty
  151. fox
  152. salubrious
  153. twinkle toes
  154. vermin
  155. yokel
  156.  
  157.  
  158. -- part contents for card part 7
  159. ----- text -----
  160. /* SortField1.2d8.c */
  161. /* ┬⌐ Trustees of Dartmouth College */
  162. /* written in LightSpeed C  ┬⌐ Think Technologies, Inc */
  163. /* by Roger Brown 3/2/88  Courseware Development Group 11/19/88 */
  164.  
  165. /* version  1.2d8 uses IUCompString for international string comparisons */
  166.  
  167. /* Distribution version. Source is for Think C┬⌐ version 4.0. */
  168.  
  169. /* This is a HyperCard XFCN that sorts the lines of a HyperCard container.
  170.      There is no limit to the number of lines except for available memory.
  171.      It uses the Lightspeed C quicksort function and it is quite fast! Only 
  172.      one pass is made over the data to find line starts.
  173.      Case is ignored in this version.
  174.          
  175.      Syntax is:
  176.    
  177.               get SortField(container)
  178.    
  179.              where    container is any hypercard container (field, variable), 
  180.                            presumed to be multi-lined.
  181.  
  182.              returns: a copy of the container sorted by line
  183.                            or error messages.
  184.             
  185.              ex.      get SortField(card field 1)
  186.                    
  187.       To compile: create a project with this,MacTraps, and the LSC┬« 
  188.       qsort.c file. Build as code resource type XFCN named SortField.
  189. */
  190.  
  191. #include "MemoryMgr.h"
  192. #include "HyperXCmd.h"
  193. #include "XCmdGlue.inc.c"
  194. #include "SetUpA4.h"
  195.  
  196. #define memoryError -1            /* marks a memory allocation error */
  197. int *order;                                    /* points to the line order array (in heap) */
  198. Handle orderHandle;                     /* handle to the line order array */ 
  199. int *lineStarts;                            /* points to array of line starts (in heap) */
  200. Handle lsHandle;                           /* handle to the line starts array */      
  201. Handle theField;                           /* handle to the input copy of the container */
  202. Handle theUCASEField;                /* handle to an upper case version of container */
  203. Handle DoSort();                        /* the sorting routine */
  204. #define NULL 0l
  205.  
  206.  
  207. /* change a string to all upper case */
  208. ucase(s)
  209. char *s;
  210. {
  211.         int i;
  212.         char c;
  213.         
  214.         for (i=0;i<strlen(s);i++) {
  215.                 s[i] = toupper(s[i]);
  216.         }
  217. }
  218.  
  219. /* Get all line starts in one sweep, changing CRs to 0 bytes so that
  220.     I have real C strings to work with later. Also process an upper case 
  221.     copy of the input data by changing CRs to 0s and upper casing 
  222.     everthing else. We process both copies because we want to sort the
  223.     upper case version but reassemble the result from the original. 
  224.    
  225.     Returns the number of lines found.
  226. */
  227.    
  228. GetLineStarts(source,ucSource)
  229. char *source,*ucSource;    /* the data source and a copy to ucase */
  230. {
  231.         int c;                                     /* character counter */
  232.         int l;                                     /* line counter */
  233.         long startsSize;                    /* size of the line starts array */
  234.         
  235.         /* allocate some memry to hold the line starts "array" */
  236.         startsSize = 128;                   /* arbitrary starting size */
  237.         lsHandle = NewHandle(startsSize*2);
  238.         if (lsHandle==NULL) {          /* handle error */
  239.                 SysBeep(60);
  240.                 return memoryError;
  241.         }
  242.         HLock(lsHandle);                  
  243.         lineStarts = (int *)*lsHandle;
  244.         
  245.         /* scan the input data to find line starts */
  246.         l = c = 0;
  247.         *lineStarts = 0;                             /* first line starts at byte 0 */
  248.         while (source[c] != 0) {               /* scan to end */
  249.                 if (source[c]==13) {            /* at end of a line */
  250.                         l++;
  251.                         *(lineStarts+l) = c+1;      /* next one starts here */
  252.                         source[c] = 0;                     /* change cr to 0 */
  253.                         ucSource[c] = 0;                 /* and do same to the ucase version */
  254.                         if (l==startsSize-10) {     /* need more room for line starts */
  255.                                 startsSize = startsSize + 128;
  256.                                 HUnlock(lsHandle);
  257.                                 SetHandleSize(lsHandle,startsSize*2);
  258.                                 if (lsHandle==NULL) {    /* oops, out of room */
  259.                                         SysBeep(60);
  260.                                         return memoryError;
  261.                                 }
  262.                                 HLock(lsHandle);
  263.                                 lineStarts = (int *)*lsHandle;  /* it might have moved */
  264.                         }
  265.                 }
  266.                 ucSource[c] = toupper(ucSource[c]);  /* change to ucase in line */
  267.                 c++;
  268.         }
  269.         if (source[c-1]==0) l--;           /* last line might not have CR */
  270.         return l+1;                         
  271. }
  272.  
  273.  
  274. /* Compare line i and line j. This function is an input to qsort. */
  275.  
  276. compare(i,j)
  277. int i,j;
  278. {
  279.     int aLen,bLen;
  280.     
  281.     aLen = strlen(*theUCASEField+*(lineStarts+order[i]));
  282.     bLen = strlen(*theUCASEField+*(lineStarts+order[j]));
  283.     return IUMagString(*theUCASEField+*(lineStarts+order[i]),
  284.                        *theUCASEField+*(lineStarts+order[j]),
  285.                        aLen,bLen);
  286. }
  287.  
  288. /* Swap line i with line j. This function is an input to qsort. */
  289.  
  290. swap(i,j)
  291. int i,j;
  292. {
  293.         int swap;
  294.         swap = order[i];             /* We don't swap them in place, just */
  295.         order[i] = order[j];       /* their positions in the order array */
  296.         order[j] = swap;
  297. }
  298.  
  299. /* Do the sort and return a handle to the sorted result */
  300.  
  301. Handle DoSort()
  302. {
  303.         Handle tempField;          /* handle to memory to build the result */
  304.         int i,j,next;
  305.         int numLines;
  306.         Str255 temp1;
  307.         OSErr err;
  308.         long orderSize;
  309.         long test;
  310.         char c;
  311.         int sLen,last;
  312.         
  313.         /* make a copy of the data to convert to upper case */
  314.         
  315.         theUCASEField = theField;
  316.         err = HandToHand(&theUCASEField);   
  317.         if (err != noErr) {                                /* some memory problem */
  318.                 tempField = NewHandle(32);       /* hope it fits */
  319.                 strcpy(*tempField,"Not enough memory to sort (1)");
  320.                 return tempField;
  321.         }
  322.         HLock(theUCASEField);                   /* lock these down so we use pointers to them */
  323.         HLock(theField);
  324.         
  325.         /* get line starts, number of lines, and an uppercase copy */
  326.         
  327.         numLines = GetLineStarts(*theField,*theUCASEField);
  328.         if (numLines == memoryError) {    /* some memory problem */
  329.                 tempField = NewHandle(32); 
  330.                 strcpy(*tempField,"Not enough memory to sort (2)");
  331.                 return tempField;
  332.         }
  333.         
  334.         /* allocate space for the order array */
  335.         
  336.         orderSize = (numLines+1)*2;             /* this is an integer array */
  337.         orderHandle = NewHandle(orderSize);
  338.         if (orderHandle==NULL) {                   /* some memory problem */
  339.                 tempField = NewHandle(32); 
  340.                 strcpy(*tempField,"Not enough memory to sort (3)");
  341.                 return tempField;
  342.         }
  343.         
  344.         /* lock it down so we can use a pointer to it */
  345.         
  346.         HLock(orderHandle);
  347.         order = (int *)*orderHandle;
  348.         
  349.          /* initialize the order list */
  350.          
  351.         for (i=0;i<numLines;i++)
  352.                 order[i] = i;    
  353.         
  354.         /* let LSC qsort do the hard work for us */
  355.         
  356.         qksort(numLines,compare,swap);
  357.         
  358.         /* Now build the sorted result: grab each line in the new order
  359.              as a C string and concatenate it to the result string. */
  360.         
  361.         tempField = theUCASEField;          /* resuse this memory, its the right size */
  362.         next = **tempField = 0;
  363.         for (i=0;i<numLines;i++) {
  364.                 sLen = 1+strlen(*theField+*(lineStarts+order[i]));
  365.                 for (j=0;j<sLen;j++,next++) {
  366.                         c = *(*theField+*(lineStarts+order[i])+j);
  367.                         if (c==0) c = '\15';      /* change 0s back to CRs */
  368.                         *(*(tempField)+next) = c;
  369.                 }
  370.         }
  371.         next--;
  372.         *(*(tempField)+next) = 0;         /* put a 0 terminator on the result */
  373.  
  374.         /* clean up */
  375.         
  376.         DisposHandle(orderHandle);
  377.         DisposHandle(lsHandle);
  378.         
  379.         /* return the result */
  380.         
  381.         return tempField;
  382. }
  383.  
  384.  
  385. /* XFCN entry point */
  386.  
  387. pascal void main(paramPtr)
  388. XCmdBlockPtr    paramPtr;
  389. {
  390.         
  391.         /* Prepare to use globals */
  392.         
  393.         RememberA0();
  394.         SetUpA4();
  395.         
  396.         /* get the input container copy */
  397.         
  398.         MoveHHi(paramPtr->params[0]);
  399.         HLock(paramPtr->params[0]);
  400.         theField = (Handle)paramPtr->params[0];
  401.         
  402.         /* do the sort */
  403.         paramPtr->returnValue = DoSort();
  404.         
  405.         /* clean up */
  406.         HUnlock (paramPtr->params[0]);
  407.         RestoreA4(); 
  408.         return;
  409. }
  410.  
  411.  
  412.  
  413. -- part contents for card part 9
  414. ----- text -----
  415. SortField version 1.2d8.c
  416. Roger Brown
  417.  
  418. SortField is an XFCN that sorts the lines of any HyperCard container.  The input is a container and the output is a sorted copy of the container data. Sorting is alphabetical.
  419.  
  420. There are many such XFCN's available.  This one has three positive features: it's fast, there is no limit to the number of lines it can sort except for the limit to available memory at the time it is used, and the source code is included here. 
  421.  
  422. INVOKING SortField
  423.  
  424.   get SortField(container)
  425.         
  426.    where   container is any HyperCard container.                                    
  427.  
  428. EXAMPLE
  429.  
  430.  ex. put SortField(card field "source") into
  431.        card field "destination"
  432.  
  433.  
  434. REVISION HISTORY
  435. 1.2d7 First public release.
  436. 1.2d8 Uses international string comparison.